package kassiopeia.plugin.test;

import kassiopeia.commons.model.plugin.Output;
import kassiopeia.commons.model.plugin.PluginDescriptor;
import kassiopeia.commons.model.xml.PluginDescriptorXmlSerializer;
import kassiopeia.commons.util.IOUtils;
import kassiopeia.plugin.Context;
import kassiopeia.plugin.Event;
import kassiopeia.plugin.Plugin;
import kassiopeia.plugin.test.assertions.EventAssertion;
import kassiopeia.plugin.test.context.TestContext;
import org.junit.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

public abstract class PluginTestSupport {

    private PluginDescriptor descriptor;
    private TestContext context = new TestContext();

    public PluginTestSupport() {
        String descriptorXml = IOUtils.getFileContent(Plugin.PLUGIN_DESCRIPTOR_PATH);
        descriptor = PluginDescriptorXmlSerializer.fromXml(descriptorXml);
    }

    protected Context getContext() {
        return context;
    }

    protected void assertAllUsedOutputsExist() {
        List<String> ids = new ArrayList<String>();
        for(Output output : descriptor.getOutputDescriptors()) {
            ids.add(output.getId());
        }

        for(String outputId : context.getRecordedOutputs()) {
            if(!ids.contains(outputId)) {
                Assert.fail("Interaction with unknown output: " + outputId + ". Is this output defined in descriptor?");
            }
        }
    }

    protected void assertNoOutgoingEvents(String outputId) {
        if(context.getRecordedOutputs().contains(outputId)) {
            Assert.fail("Unwanted interactions with output: " + outputId);
        }
    }

    protected EventAssertion assertRecordedEvent(String outputId) {
        Queue<Event> events = context.getRecordedEvents(outputId);
        if(events == null) {
            Assert.fail("There were no interactions with output: " + outputId);
        }

        if(events.isEmpty()) {
            Assert.fail("No more events was send to output: " + outputId);
        }

        return new EventAssertion(events.poll());
    }

    protected void assertRecorderEventsNumber(int expected, String outputId) {
        Queue<Event> queue = context.getRecordedEvents(outputId);
        if (queue == null) {
            Assert.fail("No such output: " + outputId);
        }
        int actual =  queue.size();
        if (expected != actual) {
            Assert.fail("Expected: " + expected + ", actual: " + actual);
        }
    }
}
